package com.example.annolog.utils;

import com.google.common.base.CaseFormat;

import com.example.annolog.constants.CommonErrorNoConstants;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.beans.Introspector;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.sql.Date;
import java.text.MessageFormat;
import java.util.*;

/**
 * StringUtils
 * @author administrator
 * @date 2019-12-12
 */
@Slf4j
public class StringUtils extends org.apache.commons.lang3.StringUtils {
    final static Logger logger= LoggerFactory.getLogger(StringUtils.class);

    /**
     * 点
     */
    private static final char EXTENSION_SEPARATOR = '.';
    /**
     * 左斜杠
     */
    private static final String FOLDER_SEPARATOR = "/";

    /**
     * 获取字符串的编码
     *
     * @param str 字符串
     * @return
     */
    public static String getEncoding(String str) {
        String encode = "GB2312";
        try {
            if (str.equals(new String(str.getBytes(encode), encode))) {
                String s = encode;
                return s;
            }
        } catch (Exception exception) {
            logger.warn("code={},msg={}", CommonErrorNoConstants.ERR_COMMON, "编码获取异常", exception);
        }
        encode = "ISO-8859-1";
        try {
            if (str.equals(new String(str.getBytes(encode), encode))) {
                String s1 = encode;
                return s1;
            }
        } catch (Exception exception1) {
            logger.warn("code={},msg={}", CommonErrorNoConstants.ERR_COMMON, "编码获取异常", exception1);
        }
        encode = "UTF-8";
        try {
            if (str.equals(new String(str.getBytes(encode), encode))) {
                String s2 = encode;
                return s2;
            }
        } catch (Exception exception2) {
            logger.warn("code={},msg={}", CommonErrorNoConstants.ERR_COMMON, "编码获取异常", exception2);
        }
        encode = "GBK";
        try {
            if (str.equals(new String(str.getBytes(encode), encode))) {
                String s3 = encode;
                return s3;
            }
        } catch (Exception exception3) {
            logger.warn("code={},msg={}", CommonErrorNoConstants.ERR_COMMON, "编码获取异常", exception3);
        }
        return "";
    }

    /**
     * 字符串分隔
     *
     * @param s     字符串
     * @param split 分隔符号
     * @return
     */
    public static List<String> str2List(String s, String split) {
        if (isBlank(s)) {
            return null;
        }
        List<String> list = new ArrayList<String>();
        StringTokenizer st = new StringTokenizer(s, split);
        while (st.hasMoreTokens()) {
            list.add(st.nextToken());
        }
        return list;
    }

    /**
     * SQL特殊字符转义
     *
     * @param content 字符串入参
     * @return
     */
    public static String escapeSql(String content) {
        if (content == null || "".equals(content.trim())) {
            return content;
        }
        return content.replaceAll("'", "''").replaceAll("/", "//").replaceAll("%", "/%").replaceAll("_", "/_")
                .replaceAll("&", "' || chr(38) || '");
    }

    /**
     * 对象信息转成字符串输出,输出内容包括字段以及其值。
     *
     * @param target 对象
     * @return
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public static String toString(Object target) {
        if (target == null) {
            return "";
        }
        try {
            if (target instanceof String) {
                return (String) target;
            } else if (target instanceof Map) {
                Map objMap = (Map) target;
                Set<Map.Entry> entrySet = objMap.entrySet();
                StringBuilder sb = new StringBuilder();
                sb.append("{");
                for (Map.Entry entry : entrySet) {
                    sb.append("\"").append(entry.getKey()).append("\"").append(":").append("\"")
                            .append(toString(entry.getValue())).append("\"").append(",");
                }
                sb.deleteCharAt(sb.length() - 1);
                sb.append("}");
                return sb.toString();
            } else if (target instanceof Collection) {
                Collection ls = (Collection) target;
                StringBuilder sb = new StringBuilder();
                sb.append("[").append(toString(ls.toArray(new Object[ls.size()]))).append("]");
                return sb.toString();
            } else if (target instanceof Object[]) {
                Object[] objArray = (Object[]) target;
                StringBuilder sb = new StringBuilder();
                for (Object obj : objArray) {
                    sb.append(toString(obj)).append(",");
                }
                return sb.toString();
            } else if (ClassUtils.isPrimitiveOrWrapper(target.getClass()) || target instanceof BigDecimal
                    || target instanceof Date || target instanceof java.util.Date) {
                return target.toString();
            } else {
                return ToStringBuilder.reflectionToString(target, ToStringStyle.JSON_STYLE);
            }
        } catch (Throwable ignore1) {
            try {
                return ReflectionToStringBuilder.toString(target, ToStringStyle.SHORT_PREFIX_STYLE);
            } catch (Throwable ignore2) {
                logger.warn("code={},msg={}", CommonErrorNoConstants.ERR_COMMON, "", ignore2);
                return target.toString();
            }
        }
    }

    /**
     * 按照驼峰规则解析，将"大写字母"变为"下划线+对应的小写字母"，如"EclpUsers"-->"eclp_users"。
     *
     * @param name 如果isBlank(name)=true，那么直接返回name。
     * @return
     */
    public static String lowerCaseByCamel(String name) {
        if (isNotBlank(name)) {
            String[] str = splitByCharacterTypeCamelCase(name);
            for (int index = 0; index < str.length; index++) {
                String lowerCase = lowerCase(str[index]);
                if (index == 0) {
                    name = lowerCase;
                } else {
                    name = name + "_" + lowerCase;
                }
            }
        }
        return name;
    }

    /**
     * 按照驼峰规则解析， 将"下划线+跟着的小写字母"变为"大写字母"，ex:"test_name"-->"testName"
     *
     * @param name 字符串入参
     * @return
     */
    public static String lowerUnderline2Camel(String name) {
        if (isNoneBlank(name)) {
            return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name);
        }

        return name;
    }

    /**
     * 字符串首字母小写 Abc->abc
     *
     * @param name 字符串入参
     * @return
     */
    public static String toLowerCaseFirstOne(String name) {
        if (Character.isLowerCase(name.charAt(0))) {
            return name;
        } else {
            return (new StringBuilder()).append(Character.isLowerCase(name.charAt(0))).append(name.substring(1))
                    .toString();
        }
    }

    /**
     * 提取文件拓展名，例如： "mypath/myfile.txt" -> "txt"。
     *
     * @param path 文件路径 (可能为 <code>null</code>)
     * @return
     */
    public static String getExtension(String path) {
        if (path == null) {
            return null;
        }
        int extIndex = path.lastIndexOf(EXTENSION_SEPARATOR);
        if (extIndex == -1) {
            return null;
        }
        int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR);
        if (folderIndex > extIndex) {
            return null;
        }
        return path.substring(extIndex + 1);
    }

    /**
     * 提取文件名，例如： "mypath/myfile.txt" -> "myfile"。
     *
     * @param path 文件路径 (可能为 <code>null</code>)
     * @return
     */
    public static String getFilename(String path) {
        if (path == null) {
            return null;
        }
        int extIndex = path.lastIndexOf(EXTENSION_SEPARATOR);
        if (extIndex == -1) {
            return null;
        }
        int folderIndex = path.lastIndexOf(FOLDER_SEPARATOR);
        if (folderIndex > extIndex) {
            return null;
        }
        return path.substring(folderIndex + 1, extIndex);
    }

    /**
     * 返回参数中第一个‘.’以后的字符串
     *
     * @param name 字符串入参
     * @return
     */
    public static String getRealName(String name) {
        name = trimToEmpty(name);
        int l = name.indexOf(".");
        return name.substring(l + 1);
    }

    /**
     * 返回参数中指定位置的字符串substring
     *
     * @param str   字符串入参
     * @param begin 开始位置
     * @param end   结束位置
     * @return
     */
    public static String subString(String str, int begin, int end) {
        str = trimToEmpty(str);
        return str.substring(begin, end);
    }

    /**
     * 是否字符串
     *
     * @param content 入参对象
     * @return
     */
    public static boolean isString(Object content) {
        return content instanceof String;
    }

    /**
     * 字符串转换成bigdecimal
     *
     * @param str 字符串入参
     * @return
     */
    public static BigDecimal toBigDecimal(String str) {

        BigDecimal bd = new BigDecimal(str);
        return bd;
    }

    /**
     * 字符串换行展示
     *
     * @param str   字符串入参
     * @param limit 指定长度
     * @return
     */
    public static String getStr(String str, int limit) {
        if (0 >= limit) {
            return str;
        }
        if (StringUtils.isBlank(str)) {
            return "";
        }
        if (str.length() <= limit) {
            return str;
        }
        StringBuffer sb = new StringBuffer();
        int md = str.length() % limit;
        int cycle = str.length() / limit;
        if (md != 0) {
            cycle = cycle + 1;
        }
        for (int i = 0; i < cycle; i++) {
            if (i == cycle - 1) {
                sb.append(str.substring(i * limit, str.length()));
            } else {
                sb.append(str.substring(i * limit, (i + 1) * limit) + "<br>");
            }
        }
        return sb.toString();
    }

    /**
     * 字符串左拼接
     *
     * @param str     原字符串
     * @param size    原字符串拼接后长度
     * @param padChar 长度不够，需填充的字符
     * @param prefix  原字符串位数补充后，加上该前缀
     * @return
     */
    public static String leftPad(String str, int size, String padChar, String prefix) {
        return trimToEmpty(prefix) + leftPad(str, size, padChar);
    }

    /**
     * 根据spring默认规则获取class的bean名称
     *
     * @param cls class类型
     * @return
     */
    public static String getBeanNameByClassName(Class<?> cls) {
        String shortClassName = ClassUtils.getShortClassName(cls);
        return Introspector.decapitalize(shortClassName);
    }

    /**
     * 通过占位符{0}格式化字符串
     *
     * @param str  字符串入参
     * @param args 格式化参数集合
     * @return
     */
    public static String formatStr(String str, Object... args) {
        String format;
        try {
            format = MessageFormat.format(str, args);
        } catch (Exception e) {
            logger.warn("code={},msg={}", CommonErrorNoConstants.ERR_COMMON, "字符串占位符匹配失败", e);
            return str;
        }
        return format;
    }

    /**
     * 将字符串str自增后返回，ex：str=0002，返回0003；
     * 如果入参非全数字，则原值返回
     *
     * @param str 字符串入参
     * @return
     */
    public static String selfIncrease(String str) {
        if (str == null) {
            return null;
        }
        int l = str.length();
        Integer strInt;
        try {
            strInt = Integer.valueOf(str);
        } catch (NumberFormatException e) {
            // 如果报错，则该字符串未全数字，原值返回
            return str;
        }
        strInt++;
        return leftPad("" + strInt, l, "0");
    }

    /**
     * 获取字符串的空组合
     *
     * @param strs 入参集合
     * @return [str..., " ", ""]
     */
    public static List<String> getStrWithBlank(String... strs) {
        List<String> ls = new ArrayList<>();
        ls.add("");
        ls.add(" ");
        for (String str : strs) {
            ls.add(trimToEmpty(str));
        }
        return ls;
    }

    /**
     * 字符串比较，忽略空值
     * <p>
     * <pre>
     * StringUtils.equals(null, null) = true
     * StringUtils.equals(null, "") = true
     * StringUtils.equals(null, "  ") = true
     * StringUtils.equals(null, "abc") = false
     * StringUtils.equals("abc", null) = false
     * StringUtils.equals("abc", "abc") = true
     * StringUtils.equals("abc", "ABC") = false
     * </pre>
     *
     * @param cs1 第一个字符串
     * @param cs2 第二个字符串
     * @return
     */
    public static boolean equalsIgnoreBlank(String cs1, String cs2) {
        return equals(trimToEmpty(cs1), trimToEmpty(cs2));
    }

    /**
     * 根据表名获取实例名
     *
     * @param tableName 表名
     * @param pre       要删除的前缀
     * @param suf       需增加的后缀
     * @return
     */
    public static String getBeanNameBytableName(String tableName, String pre, String suf) {
        return lowerUnderline2Camel(tableName.replaceFirst(pre + "_", "")) + suf;
    }

    /**
     * 多个字段转驼峰，返回数组
     *
     * @param names 入参集合
     * @return
     */
    public static String[] lowerUnderline2CamelAll(String... names) {
        if (names == null || names.length == 0) {
            return new String[0];
        }
        String[] camelNames = new String[names.length];
        for (int i = 0; i < names.length; i++) {// lowerUnderline2Camel
            camelNames[i] = lowerUnderline2Camel(names[i]);
        }
        return camelNames;
    }

    /**
     * 根据字符串，按照字节截取长度
     *
     * @param charset 编码格式
     * @param remark  原信息
     * @param length  截位长度
     * @return
     */
    public static String getBytesRemark(String charset, String remark, int length) {
        try {
            if (StringUtils.isBlank(remark) || remark.getBytes(charset).length <= length) {
                return remark;
            }
            int len = 0;
            for (int i = 0; i < remark.length(); i++) {
                // GBK编码格式 中文占两个字节 UTF-8编码格式中文占3个字节
                len += (remark.charAt(i) > 255 ? 3 : 1);
                if (len > length) {
                    return remark.substring(0, i);
                }
            }
            return remark;
        } catch (UnsupportedEncodingException e) {
            logger.warn("code={},msg={}", CommonErrorNoConstants.ERR_COMMON, "getBytesRemark失败>>>>>", e);
            return remark;
        }
    }

    /**
     * 截取字符串
     *
     * @param origRemark 原备注
     * @param length     截取长度
     * @return
     */
    public static String getRemarkByLength(String origRemark, int length) {
        if (StringUtils.isBlank(origRemark) || origRemark.length() <= length) {
            return origRemark;
        }
        return origRemark.substring(0, length);
    }

    /**
     * 功能描述:
     * [组装附言，附言格式：债券简称+业务类型+本次划款XX元。]
     *
     * @param bondName    债券简称
     * @param bizTypeName 业务类型中文
     * @param amount      划款金额 元
     * @return:
     * @author:panww
     * @create: 2020/9/18 16:18
     */
    public static String getPostscript(String bondName, String bizTypeName, BigDecimal amount) {
        String postscript = "{0}{1}本次划款{2}元";
        return StringUtils.formatStr(postscript, bondName, bizTypeName, amount);
    }

    /**
     * 字符串字节长度（中文占2）
     * */
    public static int getLength(String value) {
        int valueLength = 0;
        String chinese = "[\u0391-\uFFE5]";
        /* 获取字段值的长度，如果含中文字符，则每个中文字符长度为2，否则为1 */
        for (int i = 0; i < value.length(); i++) {
            /* 获取一个字符 */
            String temp = value.substring(i, i + 1);
            /* 判断是否为中文字符 */
            if (temp.matches(chinese)) {
                /* 中文字符长度为2 */
                valueLength += 2;
            } else {
                /* 其他字符长度为1 */
                valueLength += 1;
            }
        }
        return valueLength;
    }


}
